/*==============================================
 * Crate Maze class for GDEV engine
 *
 * Written by <YOUR NAME HERE>
 *==============================================*/
#include <fstream>  // file IO
#include <algorithm>  // for reverse
#include "Maze.h"
#include "Fail.h"

using namespace std;

CMaze::CMaze(CXMesh* pBlock, CXMesh* pCoin)
{
	mpBlock=pBlock;
	mpCoin=pCoin;
}

bool CMaze::Init(const char* name)
{
	mMaze.clear();
	// this is standard file reading code using C++
	// if you have not seen this before, you might want to study it
	ifstream in(name);	// the file
	if (!in)	FAIL(name,"Unable to load maze file");
	while(in.eof()==false)	// until the end of file
	{
		string s;
		getline(in,s);	// gets the line
		if (s.length()>1)	// skip empty lines
			mMaze.push_back(s);	// add to the list
	}
	// this chunk of code will reverse the order of the maze, making it look as the screen
	std::reverse(mMaze.begin(),mMaze.end());
	return true;
}

void CMaze::Draw()
{
	//TODO(CMaze::Draw);
//	for (....)
//		if (....)
//			mpBlock->Draw(....)
	// PS: display should be on the XZ plane, not XY
	// you should swap the XY around to make it look right

	for (unsigned i = 0; i < mMaze.size(); i++)
	{
		for (unsigned j = 0; j < mMaze[i].size(); j++)
		{
			if (mMaze[i].at(j) == '#')
			{
				mpBlock->Draw(D3DXVECTOR3((float)j,0.0f,(float)i));
			}
			else if (mMaze[i].at(j) == 'c')
			{
				mpCoin->Draw(D3DXVECTOR3((float)j,0.0f,(float)i));
			}
		}
	}
}

char CMaze::GetCell(D3DXVECTOR3 pos)
{
	//TODO(CMaze::GetCell);
	// Hint: convert the x,z to integer
    // NOTE: this is floating point values, you will need to round nearest number
    // look up the function floor() as this will help you
	// check if its outside the size of the array & return '\0'
	// otherwise return the data
    // remember the XY are reversed

	unsigned x, z;

	x = (unsigned)floor(pos.x * 100);
	z = (unsigned)floor(pos.z * 100);

	if (x % 100 > 50) x = (unsigned)ceil(pos.x);
	else //if (x % 100 < 50)
		x = (unsigned)floor(pos.x);

	if (z % 100 > 50) z = (unsigned)ceil(pos.z);
	else //if (z % 100 < 50)
		z = (unsigned)floor(pos.z);

	//unsigned x = (unsigned)floor(pos.x), z = (unsigned)floor(pos.z);
	if (z >= 0 && z <= mMaze.size())
	{
		if (x >= 0 && x <= mMaze[z].size())		
			return (mMaze[z].at(x));
	}
	return '\0';
}
bool CMaze::IsClear(D3DXVECTOR3 pos)
{
	//TODO(CMaze::IsClear);
	// this is easy, just call GetCell
    // then see if its clear

	return (GetCell(pos) == '.');
}

bool CMaze::IsClear(D3DXVECTOR3 pos,float radius)
{
	//TODO(CMaze::IsClear);
	
	return (IsClear(pos) && IsClear(pos + D3DXVECTOR3(-radius,0,radius)) && IsClear(pos + D3DXVECTOR3(radius,0,radius)) && IsClear(pos + D3DXVECTOR3(-radius,0,-radius)) && IsClear(pos + D3DXVECTOR3(radius,0,-radius)));
	//return (IsClear(pos));
}

D3DXVECTOR3 CMaze::WallSlide(D3DXVECTOR3 oldPos,D3DXVECTOR3 newPos,float radius)
{
	//TODO(CMaze::WallSlide);

	D3DXVECTOR3 temp(newPos - oldPos);
	if (IsClear(newPos-D3DXVECTOR3(temp.x,0,0), radius)) newPos-=D3DXVECTOR3(temp.x,0,0);
	else if (IsClear(newPos-D3DXVECTOR3(0,0,temp.z), radius)) newPos-=D3DXVECTOR3(0,0,temp.z);
	else newPos = oldPos;
    return newPos;
}